package com.smart.community.region.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.smart.community.commons.annotation.ApiLog;
import com.smart.community.commons.enums.ApiLogOperationType;
import com.smart.community.commons.result.Result;
import com.smart.community.region.dto.BuildingDTO;
import com.smart.community.region.dto.BuildingQueryDTO;
import com.smart.community.region.entity.Building;
import com.smart.community.region.entity.Unit;
import com.smart.community.region.service.IBuildingService;
import com.smart.community.region.service.IUnitService;
import com.smart.community.region.vo.BuildingVO;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;

/**
 * 楼栋管理控制器
 * 
 * @author Wu.Liang
 * @since 2024-12-21
 */
@Slf4j
@RestController
@RequestMapping("/region/buildings")
@Tag(name = "楼栋管理", description = "楼栋管理相关接口")
public class BuildingController {

	@Autowired
	private IBuildingService buildingService;

	@Autowired
	private IUnitService unitService;
	// ==================== 基础CRUD接口 ====================

	/**
	 * 分页查询楼栋列表
	 */
    @GetMapping
    @Operation(summary = "分页查询楼栋列表", description = "根据条件分页查询楼栋列表")
	public Result<IPage<BuildingVO>> getBuildingPage(@Parameter(description = "查询条件") BuildingQueryDTO queryDTO)
			throws Exception {
		log.info("分页查询楼栋列表，查询条件：{}", queryDTO);
		IPage<Building> buildingPage = buildingService.getBuildingPage(queryDTO);

		// 使用BuildingService的convertToVOList方法，确保社区名称正确填充
		List<BuildingVO> voList = buildingService.convertToVOList(buildingPage.getRecords());

		// 创建新的分页结果
		IPage<BuildingVO> voPage = buildingPage.convert(building -> {
			// 这里不会被执行，因为我们已经在上面转换了
			return null;
		});

		// 设置转换后的记录
		voPage.setRecords(voList);

		return Result.success(voPage);
	}

	/**
	 * 获取楼栋详情
	 */
	@GetMapping("/{buildingId}")
	@Operation(summary = "获取楼栋详情", description = "根据楼栋ID获取楼栋详细信息")
	public Result<BuildingVO> getBuildingDetail(@Parameter(description = "楼栋ID") @PathVariable Long buildingId)
			throws Exception {
		log.info("获取楼栋详情，楼栋ID：{}", buildingId);
		Building building = buildingService.getBuildingDetail(buildingId);
		if (building == null) {
			return Result.error("楼栋不存在");
		}

		// 使用BuildingService的convertToVO方法，确保社区名称正确填充
		BuildingVO vo = buildingService.convertToVO(building);
		return Result.success(vo);
	}

	/**
	 * 创建楼栋
	 */
	@ApiLog(logTitle = "创建楼栋", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.ADD)
	@PostMapping
	@Operation(summary = "创建楼栋", description = "创建新的楼栋")
	public Result<Boolean> createBuilding(@Parameter(description = "楼栋信息") @RequestBody @Valid BuildingDTO buildingDTO)
			throws Exception {
		log.info("创建楼栋，楼栋信息：{}", buildingDTO);
		boolean result = buildingService.createBuilding(buildingDTO);
		return result ? Result.success(true) : Result.error("创建楼栋失败");
	}

	/**
	 * 更新楼栋
	 */
	@ApiLog(logTitle = "更新楼栋", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.UPDATE)
	@PutMapping("/{buildingId}")
	@Operation(summary = "更新楼栋", description = "更新楼栋信息")
	public Result<Boolean> updateBuilding(@Parameter(description = "楼栋ID") @PathVariable Long buildingId,
			@Parameter(description = "楼栋信息") @RequestBody @Valid BuildingDTO buildingDTO) throws Exception {
		log.info("更新楼栋，楼栋ID：{}，楼栋信息：{}", buildingId, buildingDTO);
		buildingDTO.setId(buildingId);
		boolean result = buildingService.updateBuilding(buildingDTO);
		return result ? Result.success(true) : Result.error("更新楼栋失败");
	}

	@ApiLog(logTitle = "删除楼栋", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
	@DeleteMapping("/{buildingId}")
	@Operation(summary = "删除楼栋", description = "删除指定楼栋")
	public Result<Boolean> deleteBuilding(@Parameter(description = "楼栋ID") @PathVariable Long buildingId)
			throws Exception {
		log.info("删除楼栋，楼栋ID：{}", buildingId);
		boolean result = buildingService.deleteBuilding(buildingId);
		return result ? Result.success(true) : Result.error("删除楼栋失败");
	}

	// ==================== 查询接口 ====================

	/**
	 * 根据楼栋编号获取楼栋
	 */
	@GetMapping("/no/{buildingNo}")
	@Operation(summary = "根据楼栋编号获取楼栋", description = "根据楼栋编号获取楼栋信息")
	public Result<Building> getBuildingByNo(@Parameter(description = "楼栋编号") @PathVariable String buildingNo)
			throws Exception {
		log.info("根据楼栋编号获取楼栋，楼栋编号：{}", buildingNo);
		Building building = buildingService.getBuildingByNo(buildingNo);
		if (building == null) {
			return Result.error("楼栋不存在");
		}
		return Result.success(building);
	}

	/**
	 * 根据社区获取楼栋列表
	 */
	@GetMapping("/community/{communityId}")
	@Operation(summary = "根据社区获取楼栋列表", description = "获取指定社区下的所有楼栋")
	public Result<List<BuildingVO>> getBuildingsByCommunity(
			@Parameter(description = "社区ID") @PathVariable Long communityId) throws Exception {
		log.info("根据社区获取楼栋列表，社区ID：{}", communityId);
		List<Building> buildings = buildingService.getBuildingsByCommunity(communityId);

		// 使用BuildingService的convertToVOList方法，确保社区名称正确填充
		List<BuildingVO> result = buildingService.convertToVOList(buildings);
		return Result.success(result);
	}

	/**
	 * 楼栋布局：按楼层分组返回每层各单元的房户分布
	 */
	@GetMapping("/{buildingId}/layout")
	@Operation(summary = "获取楼栋单元分布", description = "按楼层分组返回每层各单元房户分布")
	public Result<Map<String, Object>> getBuildingLayout(
			@Parameter(description = "楼栋ID") @PathVariable Long buildingId) throws Exception {
		log.info("获取楼栋布局，楼栋ID：{}", buildingId);

		// 1) 楼栋校验与权限校验（复用服务内权限逻辑）
		Building building = buildingService.getBuildingDetail(buildingId);
		if (building == null) {
			return Result.error("楼栋不存在");
		}

		// 2) 查询该楼栋下所有单元
		List<Unit> units = unitService.getUnitsByBuildingId(buildingId);

		// 3) 预加载各单元下的房户列表（后续按楼层过滤）
		Map<Long, List<Map<String, Object>>> unitIdToHouseholds = new HashMap<>();
		for (Unit unit : units) {
			List<Map<String, Object>> listForUnit = new ArrayList<>();
			List<Object> rawList = unitService.getHouseholdsByUnit(unit.getId());
			if (rawList != null) {
				for (Object obj : rawList) {
					if (obj instanceof Map) {
						@SuppressWarnings("unchecked")
						Map<String, Object> m = (Map<String, Object>) obj;
						listForUnit.add(m);
					}
				}
			}
			unitIdToHouseholds.put(unit.getId(), listForUnit);
		}

		// 4) 组装按楼层的布局数据
		List<Map<String, Object>> floors = new ArrayList<>();
		int floorCount = building.getFloorCount() != null ? building.getFloorCount() : 0;
		for (int floor = 1; floor <= floorCount; floor++) {
			Map<String, Object> floorMap = new HashMap<>();
			floorMap.put("floorNumber", floor);

			List<Map<String, Object>> unitViews = new ArrayList<>();
			for (Unit unit : units) {
				Map<String, Object> unitMap = new HashMap<>();
				unitMap.put("id", unit.getId());
				unitMap.put("unitName", unit.getUnitName());

				// 当前楼层的房户
				List<Map<String, Object>> householdsOnFloor = new ArrayList<>();
				List<Map<String, Object>> allHouseholds = unitIdToHouseholds.getOrDefault(unit.getId(), new ArrayList<>());
				for (Map<String, Object> h : allHouseholds) {
					Object fn = h.get("floorNumber");
                    if (fn != null) {
						int f = Integer.parseInt(String.valueOf(fn));
						if (f == floor) {
							Map<String, Object> hv = new HashMap<>();
                            hv.put("id", h.get("id"));
                            hv.put("roomNumber", h.get("roomNumber"));
                            hv.put("householdCode", h.get("householdCode"));
                            hv.put("buildingId", h.get("buildingId"));
                            hv.put("unitId", h.get("unitId"));
                            hv.put("floorNumber", h.get("floorNumber"));
                            // 将房户状态映射为系统启用/禁用枚举（1/0）
                            // 规则：已入住(1)、出租(3) 视为启用(1)；空置(0)、装修中(2) 视为禁用(0)
                            Object rawStatus = h.get("status");
                            int mappedStatus = 0;
                            if (rawStatus != null) {
                                int s = Integer.parseInt(String.valueOf(rawStatus));
                                mappedStatus = (s == 1 || s == 3) ? 1 : 0;
                            }
                            hv.put("status", mappedStatus);
                            // 可选详细字段
                            hv.put("area", h.get("area"));
                            hv.put("usableArea", h.get("usableArea"));
                            hv.put("roomType", h.get("roomType"));
                            hv.put("orientation", h.get("orientation"));
                            hv.put("propertyType", h.get("propertyType"));
                            hv.put("ownerName", h.get("ownerName"));
                            hv.put("ownerPhone", h.get("ownerPhone"));
							unitMap.computeIfAbsent("households", k -> new ArrayList<>());
							householdsOnFloor.add(hv);
						}
					}
				}
				unitMap.put("households", householdsOnFloor);
				unitViews.add(unitMap);
			}

			floorMap.put("units", unitViews);
			floors.add(floorMap);
		}

		// 5) 组装最终返回数据
		Map<String, Object> result = new HashMap<>();
		result.put("buildingId", building.getId());
		result.put("buildingName", building.getBuildingName());
		result.put("communityId", building.getCommunityId()); // 添加社区ID
		result.put("floors", floors);

		return Result.success(result);
	}

	/**
	 * 根据社区ID批量查询楼栋，支持分页和树形结构
	 */
	@GetMapping("/queryByCommunity")
	@Operation(summary = "根据社区ID批量查询楼栋，支持分页和树形结构")
	public Result<?> queryBuildingsByCommunity(
			@Parameter(description = "社区ID列表，逗号分隔") @RequestParam String communityIds,
			@Parameter(description = "当前页码") @RequestParam(required = false) Integer current,
			@Parameter(description = "每页大小") @RequestParam(required = false) Integer size,
			@Parameter(description = "是否返回树形结构") @RequestParam(required = false, defaultValue = "false") Boolean tree)
			throws Exception {
		if (!StringUtils.hasText(communityIds)) {
			return Result.error("参数communityIds不能为空");
		}

		List<Long> communityIdList = new ArrayList<>();
		for (String id : communityIds.split(",")) {
			if (StringUtils.hasText(id)) {
				communityIdList.add(Long.valueOf(id.trim()));
			}
		}

		if (communityIdList.isEmpty()) {
			return Result.error("有效的社区ID不能为空");
		}

		if (Boolean.TRUE.equals(tree)) {
			List<Building> treeList = buildingService.getBuildingsTreeByCommunityIds(communityIdList);
			List<BuildingVO> voList = buildingService.convertToVOList(treeList);
			return Result.success(voList);
		} else {
			int currentPage = current != null ? current : 1;
			int pageSize = size != null ? size : 10;
			List<Building> buildings = buildingService.getBuildingsByCommunityIds(communityIdList, currentPage, pageSize);
			List<BuildingVO> voList = buildingService.convertToVOList(buildings);
			return Result.success(voList);
		}
	}

	// ==================== 状态管理接口 ====================

	/**
	 * 更新楼栋状态
	 */
	@ApiLog(logTitle = "更新楼栋状态", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.UPDATE)
	@PutMapping("/{buildingId}/status")
	@Operation(summary = "更新楼栋状态", description = "更新楼栋启用/禁用状态")
	public Result<Boolean> updateBuildingStatus(@Parameter(description = "楼栋ID") @PathVariable Long buildingId,
			@Parameter(description = "状态：0-禁用，1-启用") @RequestParam Integer status) throws Exception {
		log.info("更新楼栋状态，楼栋ID：{}，状态：{}", buildingId, status);
		boolean result = buildingService.updateBuildingStatus(buildingId, status);
		return result ? Result.success(true) : Result.error("更新楼栋状态失败");
	}

	@ApiLog(logTitle = "批量更新楼栋状态", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.UPDATE)
	@PutMapping("/batch/status")
	@Operation(summary = "批量更新楼栋状态", description = "批量更新多个楼栋的状态")
	public Result<Boolean> batchUpdateBuildingStatus(
			@Parameter(description = "楼栋ID列表") @RequestBody List<Long> buildingIds,
			@Parameter(description = "状态：0-禁用，1-启用") @RequestParam Integer status) throws Exception {
		log.info("批量更新楼栋状态，楼栋ID列表：{}，状态：{}", buildingIds, status);
		boolean result = buildingService.batchUpdateBuildingStatus(buildingIds, status);
		return result ? Result.success(true) : Result.error("批量更新楼栋状态失败");
	}

	@ApiLog(logTitle = "批量删除楼栋", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
	@DeleteMapping("/batch")
	@Operation(summary = "批量删除楼栋", description = "批量删除多个楼栋")
	public Result<Boolean> batchDeleteBuildings(@Parameter(description = "楼栋ID列表") @RequestBody List<Long> buildingIds)
			throws Exception {
		log.info("批量删除楼栋，楼栋ID列表：{}", buildingIds);
		boolean result = buildingService.batchDeleteBuildings(buildingIds);
		return result ? Result.success(true) : Result.error("批量删除楼栋失败");
	}

	// ==================== 验证接口 ====================

	/**
	 * 检查楼栋编号唯一性
	 */
	@GetMapping("/check/no")
	@Operation(summary = "检查楼栋编号唯一性", description = "检查楼栋编号是否已存在")
	public Result<Boolean> checkBuildingNoUnique(@Parameter(description = "楼栋编号") @RequestParam String buildingNo,
			@Parameter(description = "排除的楼栋ID") @RequestParam(required = false) Long excludeBuildingId)
			throws Exception {
		log.info("检查楼栋编号唯一性，楼栋编号：{}，排除楼栋ID：{}", buildingNo, excludeBuildingId);
		boolean result = buildingService.checkBuildingNoUnique(buildingNo, excludeBuildingId);
		return Result.success(result);
	}

	// ==================== 统计接口 ====================

	/**
	 * 获取楼栋统计信息
	 */
	@GetMapping("/{buildingId}/stats")
	@Operation(summary = "获取楼栋统计信息", description = "获取指定楼栋的统计信息")
	public Result<Object> getBuildingStats(@Parameter(description = "楼栋ID") @PathVariable Long buildingId)
			throws Exception {
		log.info("获取楼栋统计信息，楼栋ID：{}", buildingId);
		Object result = buildingService.getBuildingStats(buildingId);
		return Result.success(result);
	}

	// ==================== 缓存管理接口 ====================
	@ApiLog(logTitle = "清除楼栋缓存", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
	@DeleteMapping("/cache/{buildingId}")
	@Operation(summary = "清除楼栋缓存", description = "清除指定楼栋的缓存")
	public Result<Boolean> clearBuildingCache(@Parameter(description = "楼栋ID") @PathVariable Long buildingId)
			throws Exception {
		log.info("清除楼栋缓存，楼栋ID：{}", buildingId);
		buildingService.clearBuildingCache(buildingId);
		return Result.success(true);
	}

	@ApiLog(logTitle = "清除所有楼栋缓存", logType = 2, moduleName = "区域管理", operationType = ApiLogOperationType.DELETE)
	@DeleteMapping("/cache/all")
	@Operation(summary = "清除所有楼栋缓存", description = "清除所有楼栋相关的缓存")
	public Result<Boolean> clearAllBuildingCache() throws Exception {
		log.info("清除所有楼栋缓存");
		buildingService.clearAllBuildingCache();
		return Result.success(true);
	}
}